package com.fyzk.activity.trend;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.widget.Scroller;

import com.tyjc.lottery.R;
import com.fyzk.utils.ScreenUtils;

import java.util.ArrayList;
import java.util.List;

import static android.support.v4.widget.ViewDragHelper.INVALID_POINTER;
import static com.tyjc.unique._AnalaysesBaseFragment.TAG;

/**
 * Created by fanxs11 on 17/6/29.
 * 走势图baseview
 */

public abstract class TrendBaseView extends View implements TrendChooseListener{

    // 顶部背景颜色
    protected int topBg;
    // 条状背景色——灰色
    protected int bgHui;
    // 条状背景色——白色
    protected int bgBai;
    // 线条浅色
    protected int lineColor_L;
    // 线条颜色
    protected int lineColor;
    // 文本默认颜色
    protected int textDefault;
    protected int textColor666;
    protected int textColorMiss;
    protected int color_feb500;
    protected int color_showCount;
    protected int color_average;
    protected int color_maxMiss;
    protected int color_maxLian;
    protected int color_shap1;
    protected int color_shap2;
    protected int color_shap3;
    // 边界线颜色
    protected int borderColor;
    // 边界线条宽度
    protected float borderLineWidth = 0.5f;
    // 内部线条宽度
    protected float internalLinWidth = 0.5f;
    // 字体大小
    protected float textSize = 13.0f;
    // 红球背景色
    protected int redColor;
    // 蓝球背景色
    protected int blueColor;

    private Context context;

    private Scroller mScroller;

    private VelocityTracker mVelocityTracker;

    private int mMinimumVelocity;

    protected int rowVisibleCount = 15; // 正常比例下，水平方向上屏幕内可见小球个数（用于计算单位宽度）

    protected float topPaddingCount = 2.25f;      // 边界栏占据小球个数（顶部、左侧、底部  暂时设置为相同）
    protected float leftPpaddingCount = 2.25f;      // 边界栏占据小球个数（顶部、左侧、底部  暂时设置为相同）
    protected float bottomPaddingCount = 2.25f;      // 边界栏占据小球个数（顶部、左侧、底部  暂时设置为相同）
    protected int rowCount = 33;    // 中间横向占的小球数
    protected int columnCount = 100;    // 中间纵向占的小球数 (期数)
    protected int drawWidth;      // 绘制宽度
    protected int drawHeight;     // 绘制高度
    protected int unitLength;     // 单位宽度（高度）
    protected int topHeight;      // 顶部高度
    protected int bottomHeight = 0;   // 底部高度
    protected int leftWidth;      // 左侧宽度

    private int unitLength_old;    // 单位宽度（高度）

    public float scale = 0.9f;     // 当前缩放率（可保存到首选项中）
    private static final float minScale = 0.5f;     // 最小缩放率
    private static final float maxScale = 1.3f;     // 最大缩放率

    protected Paint paintBg;
    protected Paint paintText;
    protected Paint paintLine;
    protected Paint paintCircle;
    protected Paint paintTop;
    protected Paint paintLeft;
    protected Paint paintBlueLine;

    protected List<List<Integer>> infors = new ArrayList<>();
    protected List<String> phaseInfos = new ArrayList<>();
    protected int phaseLength = 6;  // 期号保留位数(高频一般保留最后2位)

    protected boolean isShowBottom = true;

    private Picture mPicture = new Picture();
    private Picture topPicture = new Picture();
    private Picture leftPicture = new Picture();

    public List<Drawinfor> bottomInfors = new ArrayList<>();

    public boolean isZX = true, isYL = true, isTJ = true;
    public boolean isChangeTJ = true;

    public TrendChooseListener listener;

    protected TrendBean trendBean;

    protected String missTitle = "miss";
    protected String hcTitle = "hc";

    protected String leftAndTopTitle = "期号";

    private OnTrendBallClick onTrendBallClickListener;

    public TrendBaseView(Context context) {
        super(context);
        initView(context);
    }

    public TrendBaseView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public TrendBaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    abstract boolean isShowBottom(List<Drawinfor> infors);

    private void initView(Context context) {
        this.context = context;
        setWillNotDraw(false);

        listener = this;

        isShowBottom = isShowBottom(bottomInfors);

        mScroller = new Scroller(context);

        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();

        topBg = context.getResources().getColor(R.color.color_eeebdb);
        bgHui = context.getResources().getColor(R.color.color_f1f2ed);
        lineColor_L = context.getResources().getColor(R.color.color_dfe0dd);
        lineColor = context.getResources().getColor(R.color.color_afb0a8);
        bgBai = context.getResources().getColor(R.color.color_ffffff);
        textDefault = context.getResources().getColor(R.color.color_000000);
        textColor666 = context.getResources().getColor(R.color.color_666666);
        textColorMiss = context.getResources().getColor(R.color.color_b4b4b4);
        borderColor = context.getResources().getColor(R.color.color_000000);
        redColor = context.getResources().getColor(R.color.color_FF4258);
        blueColor = context.getResources().getColor(R.color.color_4EA5FF);
        color_feb500 = context.getResources().getColor(R.color.color_feb500);
        color_showCount = context.getResources().getColor(R.color.color_ac5fa0);
        color_average = context.getResources().getColor(R.color.color_596fb6);
        color_maxMiss = context.getResources().getColor(R.color.color_9a6d33);
        color_maxLian = context.getResources().getColor(R.color.color_47965a);
        color_shap1 = context.getResources().getColor(R.color.color_6dc3a4);
        color_shap2 = context.getResources().getColor(R.color.color_6daec3);
        color_shap3 = context.getResources().getColor(R.color.color_8282c9);

        paintBg = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintLine.setColor(lineColor);
        paintLine.setStrokeWidth(1);

        paintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintCircle.setColor(redColor);
        paintCircle.setAntiAlias(true);
        paintCircle.setStyle(Paint.Style.FILL);

        paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintText.setColor(textDefault);
        paintText.setStrokeWidth(1);
        rectCenter = new Rect(0, 0, 0, 0);

        paintTop = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintTop.setColor(textColor666);

        paintLeft = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintLeft.setColor(textColor666);

        paintBlueLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        paintBlueLine.setAntiAlias(true);
        paintBlueLine.setStrokeWidth(3);
        paintBlueLine.setColor(blueColor);

        initData();
    }

    /**
     * 初始化数据
     */
    protected void initData() {

        unitLength = ScreenUtils.getInstance().getWidth() / rowVisibleCount;
        topHeight = (int)(unitLength * topPaddingCount);
        leftWidth = (int)(unitLength * leftPpaddingCount);
        if (!isShowBottom) {
            bottomPaddingCount = 0;
        }
        bottomHeight = (int) (unitLength * bottomPaddingCount);
        drawHeight = (int) (unitLength * (columnCount+topPaddingCount+bottomPaddingCount));
        drawWidth = (int) (unitLength * (rowCount+leftPpaddingCount));

        unitLength_old = unitLength;

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);

        toScale(scale);
    }

    /**
     * 缩放
     */
    private void toScale(float scale) {
        float newScale = this.scale * scale;
        if (newScale < minScale || newScale > maxScale) {
            return;
        }

        int unitLength = (int)(unitLength_old * newScale);
        int topHeight = (int) (unitLength * topPaddingCount);
        int leftWidth = (int) (unitLength * leftPpaddingCount);
        int bottomHeight = 0;
        int drawHeight;
        int drawWidth;
        if (!isShowBottom) {
            bottomPaddingCount = 0;
        }
        bottomHeight = (int) (unitLength * bottomPaddingCount);
        drawHeight = (int) (unitLength * (columnCount+topPaddingCount+bottomPaddingCount));

        drawWidth = (int) (unitLength * (rowCount+leftPpaddingCount));

        if (drawHeight <= getHeight() || drawWidth <= getWidth()) {
            return;
        } else {
            this.unitLength = unitLength;
            this.topHeight = topHeight;
            this.leftWidth = leftWidth;
            this.bottomHeight = bottomHeight;
            this.drawHeight = drawHeight;
            this.drawWidth = drawWidth;
        }

        if (getScrollX() > drawWidth-getWidth()) {
            setScrollX(drawWidth - getWidth());
        }
        if (getScrollY() > drawHeight-getHeight()) {
            setScrollY(drawHeight-getHeight());
        }

        recording();

        invalidate();
        this.scale = newScale;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //调用此方法滚动到目标位置
    public void smoothScrollTo(int fx, int fy) {
        int dx = fx - mScroller.getFinalX();
        int dy = fy - mScroller.getFinalY();
        smoothScrollBy(dx, dy);
    }

    private long mLastScroll;
    //调用此方法设置滚动的相对偏移
    public void smoothScrollBy(int dx, int dy) {
        // 判断是否到达边界
        if (getScrollX()+dx < 0 || getScrollX()+dx > drawWidth-getWidth()) {
            if (getScrollY()+dy < 0 || getScrollY()+dy > drawHeight-getHeight()) {

            } else {
                scrollBy(0, dy);
            }
            return;
        }
        if (getScrollY()+dy < 0 || getScrollY()+dy > drawHeight-getHeight()) {
            if (getScrollX()+dx < 0 || getScrollX()+dx > drawWidth-getWidth()) {

            } else {
                scrollBy(dx, 0);
            }
            return;
        }

        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
        scrollBy(dx, dy);
        mLastScroll = AnimationUtils.currentAnimationTimeMillis();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();
            scrollTo(x, y);
            awakenScrollBars();

            postInvalidate();
        }
    }

    private Rect clipRectCenter;

    public static final int STATE_NORMAL = 0;      // 数据正常
    public static final int STATE_REQUESTING = 1;  // 数据获取中
    public static final int STATE_NODATA = 2;      // 无数据
    public static final int STATE_ERROR = 3;       // 请求数据失败（暂时不用）
    private int stateData = STATE_REQUESTING;

    // 2.录制内容方法
    protected void recording() {
        // 中间
        Canvas canvas = mPicture.beginRecording(drawWidth, drawHeight);
        onDrawCenter(canvas, leftWidth, topHeight);
        mPicture.endRecording();

        // 顶部
        Canvas topCanvas = topPicture.beginRecording(drawWidth, topHeight);
        Rect rectTop = new Rect(leftWidth, 0, drawWidth, topHeight);
        onDrawTop(topCanvas, rectTop);
        topPicture.endRecording();

        // 左侧
        Canvas leftCanvas = leftPicture.beginRecording(leftWidth, drawHeight-topHeight-bottomHeight);
        onDrawLeft(leftCanvas, 0, topHeight);
        leftPicture.endRecording();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        clear(canvas);

        // 中间
        canvas.save();
        clipRectCenter = new Rect(getScrollX()+leftWidth,getScrollY()+topHeight,getWidth()+getScrollX(),getHeight()+getScrollY()-bottomHeight);
        canvas.clipRect(clipRectCenter);
        switch (stateData) {
            case STATE_REQUESTING:
                canvas.drawColor(Color.WHITE);
                Rect rect = new Rect(leftWidth, this.getScrollY(), getWidth()-leftWidth, getHeight()+this.getScrollY());
                paintText.setColor(textColor666);
                drawText(canvas, paintText, "数据获取中...", rect);
                break;
            case STATE_NODATA:
            case STATE_ERROR:
                canvas.drawColor(Color.WHITE);
                Rect rect_no = new Rect(leftWidth, this.getScrollY(), getWidth()-leftWidth, getHeight()+this.getScrollY());
                paintText.setColor(textColor666);
                drawText(canvas, paintText, "暂无数据!", rect_no);
                break;
            default:
                canvas.drawPicture(mPicture);
                break;
        }
        canvas.restore();

        // 顶部
        canvas.save();
        paintBg.setColor(topBg);
        canvas.clipRect(new Rect(getScrollX()+leftWidth,getScrollY(),getWidth()+getScrollX(),topHeight+getScrollY()));
        Rect rectTop = new Rect(0, getScrollY(), drawWidth, topHeight+getScrollY());
//        onDrawTop(canvas, rectTop);
        canvas.drawPicture(topPicture, rectTop);
        canvas.restore();

        // 左部
        canvas.save();
        paintBg.setColor(Color.GREEN);
        canvas.clipRect(new Rect(getScrollX(),getScrollY()+topHeight,leftWidth+getScrollX(),getHeight()-bottomHeight+getScrollY()));
//        onDrawLeft(canvas, getScrollX(), topHeight);
        Rect rectLeft = new Rect(getScrollX(), 0, leftWidth+getScrollX(), drawHeight-topHeight-bottomHeight);
        canvas.drawPicture(leftPicture, rectLeft);
        canvas.restore();

        // 底部
        if (isShowBottom) {
            canvas.save();
            paintBg.setColor(Color.WHITE);
            canvas.clipRect(new Rect(getScrollX()+leftWidth,getScrollY()+getHeight()-bottomHeight,getWidth()+getScrollX(),getScrollY()+getHeight()));
            Rect rectBottom = new Rect(leftWidth, getScrollY()+getHeight()-bottomHeight, drawWidth, getScrollY()+getHeight());
            onDrawBottom(canvas, rectBottom);
            canvas.restore();
        }

        // 左上角
        canvas.save();
        paintBg.setColor(topBg);
        Rect rectLeftAndTop = new Rect(getScrollX(),getScrollY(), leftWidth+getScrollX(),topHeight+getScrollY());
        canvas.drawRect(rectLeftAndTop, paintBg);
        drawText(canvas, paintTop, leftAndTopTitle, rectLeftAndTop);
        canvas.drawLine(rectLeftAndTop.right-1, rectLeftAndTop.top, rectLeftAndTop.right-1, rectLeftAndTop.bottom, paintLine);
        canvas.drawLine(rectLeftAndTop.left, rectLeftAndTop.bottom-1, rectLeftAndTop.right, rectLeftAndTop.bottom-1, paintLine);
        canvas.restore();

        // 左下角
        if (isShowBottom) {
            canvas.save();
            paintBg.setColor(Color.WHITE);
            Rect rectLeftAndBottom = new Rect(getScrollX(), getScrollY()+getHeight()-bottomHeight, leftWidth+getScrollX(),getScrollY()+getHeight());
            canvas.drawRect(rectLeftAndBottom, paintBg);
            drawText(canvas, paintTop, "选号：", new Rect(rectLeftAndBottom.left, rectLeftAndBottom.top, rectLeftAndBottom.right, rectLeftAndBottom.top+rectLeftAndBottom.height()*2/3));
            drawText(canvas, paintTop, "已选：", new Rect(rectLeftAndBottom.left, rectLeftAndBottom.top+rectLeftAndBottom.height()/2, rectLeftAndBottom.right, rectLeftAndBottom.bottom));
//            canvas.drawLine(rectLeftAndBottom.right-1, rectLeftAndBottom.top, rectLeftAndBottom.right-1, rectLeftAndBottom.bottom, paintLine);
            canvas.drawLine(rectLeftAndBottom.left, rectLeftAndBottom.top+1, rectLeftAndBottom.right, rectLeftAndBottom.top+1, paintLine);
            canvas.restore();
        }

    }

    /**
     * 清除
     * @param canvas
     */
    private void clear(Canvas canvas) {
        Paint paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawPaint(paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    }

    /**
     * 绘制顶部内容
     * @param canvas
     * @param rect
     */
    protected void onDrawTop(Canvas canvas, Rect rect) {
        canvas.drawRect(rect, paintBg);
    }

    /**
     * 绘制左侧内容
     * @param canvas
     */
    protected void onDrawLeft(Canvas canvas, int left, int top) {
        int startColumn = 0;
        paintLine.setColor(lineColor);
        // 中间
        for (int i = startColumn; i < columnCount; i++) {
            rectCenter.left = left;
            rectCenter.right = rectCenter.left + leftWidth;
            rectCenter.top = top + i*unitLength;
            rectCenter.bottom = rectCenter.top + unitLength;

            if (i % 2 == 0) {
                paintBg.setColor(bgBai);
            } else {
                paintBg.setColor(bgHui);
            }
            canvas.drawRect(rectCenter, paintBg);
            paintLine.setColor(textDefault);
            if (isTJ) {
                if (i == phaseInfos.size()-4) {
                    paintLeft.setColor(color_showCount);
                    canvas.drawLine(rectCenter.left, rectCenter.top, rectCenter.right, rectCenter.top, paintLine);
                } else if (i == phaseInfos.size() - 3) {

                    paintLeft.setColor(color_average);
                } else if (i == phaseInfos.size() - 2) {

                    paintLeft.setColor(color_maxMiss);
                } else if (i == phaseInfos.size() - 1) {

                    paintLeft.setColor(color_maxLian);
                } else {
                    paintLeft.setColor(textColor666);
                }
            } else {
                paintLeft.setColor(textColor666);
            }
            canvas.drawLine(rectCenter.left, rectCenter.bottom, rectCenter.right, rectCenter.bottom, paintLine);
            String phase = ""+i;
            if (phaseInfos.size() > 0) {
                try {
                    phase = phaseInfos.get(i);
                } catch (Exception e) {

                }
            }
            drawText(canvas, paintLeft, phase+"", rectCenter);
            canvas.drawLine(rectCenter.right-1, rectCenter.top, rectCenter.right-1, rectCenter.bottom, paintLine);
        }
    }

    /**
     * 绘制底部内容
     * @param canvas
     * @param rect
     */
    protected void onDrawBottom(Canvas canvas, Rect rect) {
        canvas.drawRect(rect, paintBg);
        canvas.drawLine(rect.left, rect.top+1, rect.right, rect.top+1, paintLine);
    }

    Rect rectCenter;

    /**
     * 绘制中间内容
     * @param canvas
     */
    protected void onDrawCenter(Canvas canvas, int left, int top) {

        rectCenter = new Rect(left, top, drawWidth, drawHeight);
        canvas.drawColor(Color.WHITE);
    }

    private float mLastX;
    private float mLastY;
    private boolean mIsBeingDragged;

    private int mActivePointerId;

    private boolean isPointer = false;  // 是否是双手势
    float oldDist = 1f;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        int actionId = MotionEventCompat.getActionMasked(event);
        switch (actionId) {
            case MotionEvent.ACTION_DOWN:
                isPointer = false;
                mLastX = event.getX();
                mLastY = event.getY();
                mIsBeingDragged = true;
                mActivePointerId = event.getPointerId(0);
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                if (getParent() != null) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }

                for (Drawinfor drawInfor: bottomInfors) {
                    if (drawInfor.rect != null && drawInfor.rect.contains((int)mLastX+getScrollX(),(int)mLastY+getScrollY())) {
                        drawInfor.isCheck = !drawInfor.isCheck;
                        invalidate();
                        if (onTrendBallClickListener != null) {
                            onTrendBallClickListener.onBallClick();
                        }
                        break;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                isPointer = true;
                oldDist = spacing(event);

                break;
            case MotionEvent.ACTION_MOVE:
                if (mIsBeingDragged) {

                    if (isPointer) {
                        float newDist = spacing(event);
                        float scale = newDist / oldDist;
                        toScale(scale);
                        oldDist = newDist;
                    } else {
                        // Scroll to follow the motion event
                    }
                    final int activePointerIndex = event.findPointerIndex(mActivePointerId);
                    final float y = event.getY(activePointerIndex);
                    final int deltaY = (int) (mLastY - y);
                    mLastY = y;

                    final float x = event.getX(activePointerIndex);
                    final int deltaX = (int) (mLastX - x);
                    mLastX = x;
                    smoothScrollBy(deltaX, deltaY);
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                isPointer = false;
                onSecondaryPointerUp(event);
                break;
            case MotionEvent.ACTION_UP:
                isPointer = false;
                if (mIsBeingDragged) {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000);
                    int initialVelocitx = (int) velocityTracker.getXVelocity(mActivePointerId);
                    int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

                    if(Math.abs(initialVelocitx) > initialVelocitx || Math.abs(initialVelocity) > mMinimumVelocity) {
                        fling(-initialVelocitx, -initialVelocity);
                    }

                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;

                    releaseVelocityTracker();
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                if (mIsBeingDragged) {
                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;
                    releaseVelocityTracker();
                }
                break;
            default:
        }
        return mIsBeingDragged;
    }

    // 触碰两点间距离
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);

        return (float) Math.sqrt((double)(x * x + y * y));
    }

    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastX = ev.getX(newPointerIndex);
            mLastY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }

    /**
     * Fling the scroll view
     */
    public void fling(int velocityX, int velocityY) {

        mScroller.fling(getScrollX(), getScrollY(), velocityX, velocityY,
                0, Math.max(0, drawWidth - getWidth()),
                0, Math.max(0, drawHeight - getHeight()));

        invalidate();
    }

    /**
     *
     * @param event 向VelocityTracker添加MotionEvent
     *
     * @see android.view.VelocityTracker#obtain()
     * @see android.view.VelocityTracker#addMovement(MotionEvent)
     */
    private void acquireVelocityTracker(final MotionEvent event) {
        if(null == mVelocityTracker) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }

    /**
     * 释放VelocityTracker
     *
     * @see android.view.VelocityTracker#clear()
     * @see android.view.VelocityTracker#recycle()
     */
    private void releaseVelocityTracker() {
        if(null != mVelocityTracker) {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    /**
     * 绘制文字
     * @param canvas
     * @param paint
     * @param text
     * @param rect
     */
    protected void drawText(Canvas canvas, Paint paint, String text, Rect rect){
        paint.setAntiAlias(true);
        paint.setTextSize(textSize * ScreenUtils.getInstance().getDensity() * this.scale);
        Paint.FontMetrics fm = paint.getFontMetrics();
        int baseLine = (int)(rect.top + (rect.bottom - rect.top - fm.bottom + fm.top) / 2 - fm.top);
        canvas.drawText(text, rect.centerX() - (paint.measureText(text)/2), baseLine, paint);
    }

    public List<List<Integer>> getInfors() {
        return infors;
    }

    /**
     * 设置数据（普通数字彩）
     * @param infors
     * @param phaseInfos
     */
    public void setInfors(List<List<Integer>> infors, List<String> phaseInfos, int chooseId) {
        this.chooseId = chooseId;
        if (infors == null || infors.size() == 0) {
            return;
        }
        this.infors = infors;
        this.phaseInfos = phaseInfos;

        if (infors != null && infors.size() > 0) {
            if (isTJ) {
                columnCount = infors.size();
            } else {
                columnCount = infors.size() - 4;
            }
            rowCount = infors.get(0).size();
        }
        drawWidth = (int) (unitLength * (rowCount+leftPpaddingCount));
        if (!isShowBottom) {
            bottomPaddingCount = 0;
        }
        drawHeight = (int) (unitLength * (columnCount+topPaddingCount+bottomPaddingCount));

        if (drawHeight <= getHeight()) {
            scale = 0.9f;
            toScale(1.0f);
        }

        if (isChangeTJ) {
            setScrollY(drawHeight - getHeight());
        }

        recording();
        invalidate();
    }

    /**
     * 新数据（高频）
     * @param trendBean
     */
    public void setTrendBean(TrendBean trendBean) {
        this.trendBean = trendBean;

        setMissInfors(payType,chooseId);
    }

    protected List<List<String>> missInfors = new ArrayList<>();
    public int payType = 0;
    public int chooseId = R.id.trend_choose_rb2;
    public void setMissInfors(int paytype, int chooseId) {
        this.payType = paytype;
        this.chooseId = chooseId;
        if (trendBean == null) {
            return;
        }
        this.phaseInfos = trendBean.getPhaseInfos(phaseLength);

        missInfors = trendBean.getMissValues(paytype, chooseId, missTitle, hcTitle);
        Log.d(TAG, "setMissInfors: size:"+missInfors.size());

        if (missInfors != null && missInfors.size() > 0) {
            setColumn(paytype, chooseId);
        }
        if (!isShowBottom) {
            bottomPaddingCount = 0;
        }
        drawHeight = (int) (unitLength * (columnCount+topPaddingCount+bottomPaddingCount));

        if (drawHeight < getHeight()) {
            drawHeight = getHeight();
        }

        if (drawWidth < getWidth()) {
            drawWidth = getWidth();
        }

        if (isChangeTJ) {
            setScrollY(drawHeight - getHeight());
        }

        recording();
        if (drawHeight > getHeight()) {
            setScrollY(drawHeight - getHeight());
        } else {
            setScrollY(0);
        }
        setScrollX(0);
        invalidate();
    }

    protected void setColumn(int paytype, int chooseId) {
        switch (chooseId) {
            case R.id.trend_choose_rb2:
                if (isTJ) {
                    columnCount = missInfors.size();
                } else {
                    columnCount = missInfors.size() - 4;
                }
                break;
            case R.id.trend_choose_rb3:
                switch (paytype) {
                    case 8:
                    case 10:
                        if (isTJ) {
                            columnCount = missInfors.size();
                        } else {
                            columnCount = missInfors.size() - 4;
                        }
                        break;
                    default:
                        columnCount = missInfors.size();
                        break;
                }
                break;
            case R.id.trend_choose_rb4:
                switch (paytype) {
                    case 10:
                        if (isTJ) {
                            columnCount = missInfors.size();
                        } else {
                            columnCount = missInfors.size() - 4;
                        }
                        break;
                    default:
                        columnCount = missInfors.size();
                        break;
                }
                break;
            default:
                columnCount = missInfors.size();
                break;
        }
    }

    @Override
    public void onChooseClick(int id) {
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
    }

    @Override
    public void onChangePayType(int id) {
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }
    }

    public void setColumnCount(int columnCount, boolean isHc) {
        if (!isHc) {
            if (trendBean != null && trendBean.getMisses() != null && trendBean.getMisses().size() > 0) {
                this.columnCount = trendBean.getMisses().size();
            } else {
                this.columnCount = columnCount;
            }
        } else {
            this.columnCount = columnCount;
        }

        drawHeight = (int) (unitLength * (columnCount+topPaddingCount+bottomPaddingCount));
        if (drawHeight < getHeight()) {
            drawHeight = getHeight();
        }
    }

    public void setRowCount(int rowCount) {
        this.rowCount = rowCount;
        drawWidth = (int) (unitLength * (rowCount+leftPpaddingCount));
        if (drawWidth < getWidth()) {
            drawWidth = getWidth();
        }
    }

    public class Drawinfor {
        public Rect rect;
        public String text;
        public int type;
        public boolean isCheck;
        public int shapColor;
        public int textColor;
        public boolean isFill = true;  // 是否填充
        public int shapType;    // 图形类型：0 圆形，1 矩形
        public int findCount = 1;   // 出现次数（快三）
    }

    // 通用
    protected void drawShap(Canvas canvas, List<Drawinfor> drawinfors, boolean isShwoZx) {
        if (drawinfors.size() == 0) {
            return;
        }
        if (isShwoZx) {
            List<Rect> lineRects = new ArrayList<>();
            for (int i = 0; i < drawinfors.size(); i++) {
                lineRects.add(drawinfors.get(i).rect);
            }

            paintBlueLine.setColor(drawinfors.get(0).shapColor);
            // 画蓝球折线
            for (int i = 0; i < lineRects.size(); i++) {
                if (i > 0) {
                    Rect rectLine1 = lineRects.get(i-1);
                    Rect rectLine2 = lineRects.get(i);
                    canvas.drawLine(rectLine1.centerX(), rectLine1.centerY(), rectLine2.centerX(), rectLine2.centerY(), paintBlueLine);
                }
            }
        }

        for (int i = 0; i < drawinfors.size(); i++) {
            paintText.setColor(drawinfors.get(i).textColor);
            paintCircle.setColor(drawinfors.get(i).shapColor);
            Rect rectShap = drawinfors.get(i).rect;

            if (drawinfors.get(i).isFill) {
                paintCircle.setStyle(Paint.Style.FILL);
            } else {
                paintCircle.setStyle(Paint.Style.STROKE);
            }
            switch (drawinfors.get(i).shapType) {
                case 0:
                    Rect rectCircle = rectShap;
                    canvas.drawCircle(rectCircle.centerX(), rectCircle.centerY(), rectCircle.width()/2-4, paintCircle);
                    break;
                case 1:
                    int paddingW = rectShap.width()/8;
                    int paddingH = rectShap.height()/8;
                    Rect rect1 = new Rect(rectShap.left+paddingW,rectShap.top+paddingH, rectShap.right-paddingW, rectShap.bottom-paddingH);
                    canvas.drawRect(rect1,paintCircle);
                    break;
                default:
                    break;
            }

            drawText(canvas, paintText, drawinfors.get(i).text, rectShap);

            // 该号码出现次数
            if (drawinfors.get(i).findCount > 1) {
                Rect findRect = new Rect(rectShap.right-rectShap.width()/2,rectShap.top, rectShap.right, rectShap.top+rectShap.height()/2);
                paintCircle.setColor(color_average);
                canvas.drawCircle(findRect.centerX(), findRect.centerY(), findRect.width()/2-4, paintCircle);
                paintText.setColor(color_feb500);
                textSize = 10;
                drawText(canvas, paintText, drawinfors.get(i).findCount+"", findRect);
                textSize = 13;
            }

        }
    }

    public void setStateData(int stateData) {
        this.stateData = stateData;
        this.invalidate();
    }

    public OnTrendBallClick getOnTrendBallClickListener() {
        return onTrendBallClickListener;
    }

    public void setOnTrendBallClickListener(OnTrendBallClick onTrendBallClickListener) {
        this.onTrendBallClickListener = onTrendBallClickListener;
    }
}

interface OnTrendBallClick{
    void onBallClick();
}
